package com.xinghe.sharedevice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.share.common.core.exception.ServiceException;
import com.share.common.security.utils.SecurityUtils;
import com.xinghe.sharedevice.domain.Cabinet;
import com.xinghe.sharedevice.domain.CabinetSlot;
import com.xinghe.sharedevice.domain.CabinetType;
import com.xinghe.sharedevice.domain.PowerBank;
import com.xinghe.sharedevice.mapper.CabinetMapper;
import com.xinghe.sharedevice.mapper.CabinetTypeMapper;
import com.xinghe.sharedevice.mapper.cabinetSlotMapper;
import com.xinghe.sharedevice.service.ICabinetService;
import com.xinghe.sharedevice.service.IPowerBankService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 星河一叶Ck
 * @date 2025/5/26
 */

@Service
@RequiredArgsConstructor
public class cabinetServiceImpl extends ServiceImpl<CabinetMapper, Cabinet> implements ICabinetService {

    private final CabinetMapper cabinetMapper;
    private final CabinetTypeMapper cabinetTypeMapper;
    private final cabinetSlotMapper cabinetSlotMapper;
    private final IPowerBankService powerBankService;

    @Override
    public List<Cabinet> selectCabinetList(Cabinet cabinet) {
        return cabinetMapper.selectCabinetList(cabinet);
    }

    /**
     * 增加充电宝柜机的信息
     * @param cabinet 充电宝柜机信息
     * @return int
     */
    @Override
    public int saveCabinet(Cabinet cabinet) {
        // 首先查看柜机是否存在
        long count = this.count(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getCabinetNo, cabinet.getCabinetNo()));
        if (count > 0) {
            throw new ServiceException("该柜机编号已存在");
        }

        // 根据柜机类型id查询柜机类型
        CabinetType cabinetType = cabinetTypeMapper.selectById(cabinet.getCabinetTypeId());

        // 设置总插槽数量和可用插槽数量 将其他的都设置为默认值
        cabinet.setTotalSlots(cabinetType.getTotalSlots());
        cabinet.setFreeSlots(cabinetType.getTotalSlots());
        cabinet.setUsedSlots(0);
        cabinet.setAvailableNum(0);
        cabinet.setCreateTime(new Date());
        cabinet.setCreateBy(SecurityUtils.getUsername());
        this.save(cabinet);

        Integer size = cabinetType.getTotalSlots();
        for (int i = 0;i < size; i ++) {
            CabinetSlot cabinetSlot = new CabinetSlot();
            cabinetSlot.setCabinetId(cabinet.getId());
            cabinetSlot.setSlotNo(i + 1 + ""); // 该插槽的充电宝 1号开始递增
            cabinetSlot.setCreateTime(new Date());
            cabinetSlot.setCreateBy(SecurityUtils.getUsername());
            cabinetSlotMapper.insert(cabinetSlot);
        }

        return 1;
    }

    /**
     * 修改充电宝柜机信息
     * @param cabinet 修改的信息
     * @return int
     */
    @Override
    public int updateCabinet(Cabinet cabinet) {
        // 首先查询id是否有
        if (cabinet.getId() == null) {
            throw new ServiceException("id不存在");
        }

        // 获取旧数据
        Cabinet oldCabinet = this.getById(cabinet.getId());
        // 如果柜机不为空且状态不为0的情况
        if (oldCabinet != null && !oldCabinet.getStatus().equals("0")) {
            throw new ServiceException("该柜机已投放，无法修改");
        }

        // 判断柜机的编号是否改变
        if (!oldCabinet.getCabinetNo().equals(cabinet.getCabinetNo())) {
            // 根据新编号查询是否已经被使用
            long count = this.count(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getCabinetNo, cabinet.getCabinetNo()));
            if (count > 0) {
                throw new ServiceException("该柜机编号已存在");
            }
        }

        // 判断是否修改了柜机类型
        if (oldCabinet.getCabinetTypeId().longValue() != cabinet.getCabinetTypeId().longValue()) {
            // 修改柜机类型
            CabinetType cabinetType = cabinetTypeMapper.selectById(cabinet.getCabinetTypeId());
            // 设置总插槽数量和可用插槽数量
            cabinet.setTotalSlots(cabinetType.getTotalSlots());
            cabinet.setFreeSlots(cabinetType.getTotalSlots());
            cabinet.setUpdateTime(new Date());
            cabinet.setUpdateBy(SecurityUtils.getUsername());
            cabinet.setUsedSlots(0);
            cabinet.setAvailableNum(0);
            this.updateById(cabinet);

            // 删除所有插槽 => 重置所有插槽
            cabinetSlotMapper.delete(new LambdaQueryWrapper<CabinetSlot>().eq(CabinetSlot::getCabinetId, cabinet.getId()));
            Integer size = cabinetType.getTotalSlots();
            for (int i = 0;i < size; i ++) {
                CabinetSlot cabinetSlot = new CabinetSlot();
                // 设置所有的默认值
                cabinetSlot.setUpdateTime(new Date());
                cabinetSlot.setUpdateBy(SecurityUtils.getUsername());
                cabinetSlot.setCabinetId(cabinet.getId());
                cabinetSlot.setSlotNo(i + 1 + "");
                cabinetSlotMapper.insert(cabinetSlot);
            }
        } else {
            // 若类型没改变 只需要改本表充电柜
            cabinet.setUpdateTime(new Date());
            cabinet.setUpdateBy(SecurityUtils.getUsername());
            this.updateById(cabinet);
        }

        return 1;
    }

    @Override
    public int removeCabinet(List<Long> idList) {
        // 删除充电柜机
        this.removeBatchByIds(idList);
        // 删除插槽 => 用in表示只要和集合中id是一样的充电柜机id 就进行删除
        cabinetSlotMapper.delete(new LambdaQueryWrapper<CabinetSlot>().in(CabinetSlot::getCabinetId, idList));
        return 1;
    }

    /**
     * 搜索未使用的充电宝柜机
     * @param keyword 关键字
     * @return List<Cabinet>
     */
    @Override
    public List<Cabinet> searchNoUseList(String keyword) {
        // 和搜索的关键字模糊查询且是可以正常使用的
        return cabinetMapper.selectList(new LambdaQueryWrapper<Cabinet>()
                .like(Cabinet::getCabinetNo, keyword)
                .eq(Cabinet::getStatus, "0"));
    }

    @Override
    public Map<String, Object> getAllInfo(Long id) {
        // 查询柜机信息
        Cabinet cabinet = this.getById(id);

        // 查询插槽信息
        List<CabinetSlot> CabinetSlotList = cabinetSlotMapper.selectList(
                                    new LambdaQueryWrapper<CabinetSlot>()
                                            .eq(CabinetSlot::getCabinetId, cabinet.getId()));

        // 获取可用充电宝id列表
        List<Long> powerBankIdList = CabinetSlotList.stream()
                .filter(item -> null != item.getPowerBankId()) // 筛选出有充电宝的插槽
                .map(CabinetSlot::getPowerBankId) // 获取充电宝id
                .collect(Collectors.toList()); // 转换成list

        if (!CollectionUtils.isEmpty(powerBankIdList)) {
            // 直接调用 列表中每一个id 查询到实体类
            List<PowerBank> powerBankList = powerBankService.listByIds(powerBankIdList);
            Map<Long, PowerBank> powerBankIdToPowerBankMap = powerBankList.stream()
                    // key 是 充电宝id 值是充电宝
                    .collect(Collectors.toMap(PowerBank::getId, PowerBank -> PowerBank));
            // 根据充电宝id 赋值该充电宝详细信息
            CabinetSlotList.forEach(item -> {
                item.setPowerBank(powerBankIdToPowerBankMap.get(item.getPowerBankId()));
            });
        }
        // 柜机位第一个key 然后柜机值 第二个key是插槽 然后插槽详细信息
        Map<String, Object> result = Map.of("cabinet", cabinet, "cabinetSlotList", CabinetSlotList);
        return result;
    }


}

